import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.CertificateFactory;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.security.auth.Subject;
import javax.security.auth.x500.X500Principal;

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.DERObject;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERUTF8String;


/**A Simple Certificate Verifier that checks if the certificate hasn't
 * been tampered or modified. Extracts all the information and uses
 * the included public key to calculate the signature hash and checks it against
 * the signature in the certificate
 * @author Bao To & Chris Yereaztian
 *
 */

/*
 * Certificate that should be validated Certificate: 
 * Data: Version: 3 (0x2)
 * Serial Number: 8b:37:8e:20:e2:7a:d6:f1 Signature Algorithm:
 * sha1WithRSAEncryption Issuer: C=CH, ST=Aargau, L=Windisch, O=FHNW, OU=NS,
 * CN=Chris Yereaztian/emailAddress=chris.yereaztian@students.fhnw.ch Validity
 * Not Before: Oct 1 13:59:09 2011 GMT Not After : Sep 28 13:59:09 2021 GMT
 * Subject: C=CH, ST=Aargau, L=Windisch, O=FHNW, OU=NS, CN=Chris
 * Yereaztian/emailAddress=chris.yereaztian@students.fhnw.ch Subject Public Key
 * Info: Public Key Algorithm: rsaEncryption Public-Key: (4096 bit) Modulus:
 * 00:bb:88:0a:38:90:3b:a3:cf:3a:e2:81:f1:34:32:
 * f7:c6:17:da:e8:27:4c:e5:eb:89:75:ff:0b:fc:d3:
 * 6b:5f:b0:01:56:c7:16:b4:54:85:9f:f1:9e:1a:90:
 * 91:ba:99:bc:aa:1e:78:9b:55:7d:ce:5c:de:f9:42:
 * 35:1d:bd:3d:ae:c2:b4:f9:32:ba:f2:14:0e:6f:4f:
 * 60:3c:9d:52:ea:00:09:7c:f7:df:37:ef:bb:64:83:
 * 33:80:a9:7d:b7:70:bc:fb:16:4c:3d:6b:dd:5a:40:
 * 39:d1:dd:01:06:8d:d4:09:33:53:80:2f:3a:9b:94:
 * a6:ea:89:46:c4:79:06:6e:2a:7c:8b:1f:5c:42:59:
 * b5:00:f6:08:6d:f6:cc:fa:97:d8:98:22:71:31:cc:
 * 6a:1e:40:49:81:0f:32:ad:7b:9b:a7:f8:0b:78:0f:
 * ec:13:d4:ba:e6:e2:d9:21:f9:61:38:f0:c7:ee:74:
 * 6f:80:05:43:8a:2d:de:21:76:a2:29:d4:87:d1:6c:
 * 88:2b:bf:d9:fb:e0:e9:fa:83:4d:cf:6b:6b:a6:b8:
 * ec:1d:4c:db:95:26:64:d1:a8:22:07:68:99:3c:5a:
 * 7f:b7:68:f9:6d:97:ce:45:05:31:f7:8e:a3:19:c5:
 * a2:ee:cc:09:2b:60:3c:14:91:39:99:23:5d:a1:23:
 * 71:00:20:5f:fd:99:8b:ae:69:4d:d9:05:a8:85:30:
 * fd:8d:5c:b3:1e:93:0c:29:07:af:80:81:4b:36:6b:
 * 7b:29:1c:35:35:bf:93:29:9f:83:b4:17:3d:86:c7:
 * a1:d9:0f:e2:38:2e:2d:c5:a1:2d:68:78:35:52:3c:
 * f6:7e:97:01:72:fc:0a:42:19:73:ff:3d:9d:fa:27:
 * 93:f1:44:02:30:e0:98:95:50:01:ff:0b:54:c1:70:
 * cc:87:bb:5b:c7:df:54:35:f6:27:c4:99:14:1d:37:
 * 44:cb:e4:cb:5f:28:e8:69:ab:0f:e7:9f:27:d7:96:
 * a3:44:66:43:04:c2:14:1a:93:c1:c4:62:43:6b:d4:
 * 8c:94:bd:f1:16:4a:bc:d6:8d:8e:12:86:33:96:bd:
 * 07:90:ee:56:4d:8a:1a:8f:98:d2:c0:d3:a2:05:66:
 * 80:a8:3c:70:d0:b7:ed:34:91:15:5d:d8:88:89:0f:
 * fc:fb:f4:03:2e:15:bb:81:e3:1a:74:0f:1f:28:8a:
 * 0d:84:7b:0e:1f:c8:ca:87:ab:94:a5:aa:ef:5b:e5:
 * 15:24:3e:bb:5c:8b:fc:04:7b:12:29:1a:d4:e0:c5:
 * 76:74:e0:1a:1f:db:70:9f:56:ad:71:aa:91:0c:4c:
 * 58:e0:4d:26:dc:61:f3:36:f6:c8:13:0c:f6:b1:50: 4a:22:05 Exponent: 65537
 * (0x10001) X509v3 extensions: X509v3 Subject Key Identifier:
 * CC:E7:4C:86:5A:D7:84:A6:6E:96:2E:84:1A:1C:F4:6A:2E:85:A7:A7 X509v3 Authority
 * Key Identifier:
 * keyid:CC:E7:4C:86:5A:D7:84:A6:6E:96:2E:84:1A:1C:F4:6A:2E:85:A7:A7
 * 
 * X509v3 Basic Constraints: CA:TRUE Signature Algorithm: sha1WithRSAEncryption
 * 04:65:57:13:32:ff:07:0a:9b:df:72:7d:96:75:6e:7e:d2:5b:
 * 25:d1:30:76:fb:db:9e:0c:de:69:4b:d2:5f:13:2e:02:68:46:
 * 4f:ad:6b:f8:21:01:4d:92:34:c6:d8:ab:5d:2c:89:0f:9d:8f:
 * eb:a1:50:ef:c2:e8:ab:a6:0d:fa:65:a4:12:32:6e:e2:7d:f9:
 * f2:2b:b2:38:a8:9a:62:b2:7a:27:9d:e9:0d:a8:4b:b3:8e:f3:
 * 55:e5:fa:71:c5:0a:5e:df:ab:1e:51:5d:2d:af:8b:de:dd:05:
 * 1c:17:2d:1d:e2:9d:69:d0:c6:3c:85:a2:26:98:d8:c2:79:d7:
 * b2:88:d6:23:a1:b8:c4:54:6d:59:9c:7d:9d:db:f6:f3:4c:92:
 * 9c:9a:31:e4:32:be:bd:17:d5:8b:99:ba:cd:65:ac:1a:6a:b2:
 * c1:15:19:45:cd:6c:e1:fc:8e:ea:d5:4d:33:1c:d4:04:03:49:
 * 4b:8d:62:13:c9:7e:3f:83:a2:fd:ef:a1:d6:a6:93:40:06:0d:
 * f5:62:78:8b:5a:bc:8d:9a:d2:fb:a3:5c:d9:b0:f9:31:69:22:
 * c8:f3:5d:90:c3:73:7d:ec:9f:59:12:fb:f9:4c:e1:76:d3:ba:
 * c7:93:7b:d3:1d:3c:3c:fa:1c:54:1b:e7:bf:0f:e0:5f:cb:0c:
 * 5a:33:5e:35:aa:08:82:78:c1:df:ff:a4:ed:50:da:f9:51:a9:
 * a1:95:d5:99:ad:dc:e2:14:2e:7e:f6:44:30:96:c8:0b:e0:b7:
 * c3:ba:93:0e:d3:05:d5:3d:17:a9:6c:f5:12:03:92:7a:7b:d3:
 * f6:60:9f:3c:d7:be:cc:ad:15:10:a9:b8:50:21:ea:7f:3c:4a:
 * 4c:19:ce:9f:0e:ac:b7:78:78:30:d6:b7:62:91:06:e1:c1:e6:
 * cb:76:15:81:fc:d0:1d:36:b2:0f:a7:82:9a:4b:bb:1e:90:5e:
 * 48:7f:87:bd:ac:df:9b:00:8a:87:0c:fb:ea:e4:7a:d5:60:6e:
 * 6a:f8:eb:f4:99:c0:a1:b0:d5:2f:c6:87:d4:32:1e:dd:e9:38:
 * 7d:bd:a6:85:cc:5a:8e:6d:ea:91:b6:c3:37:95:f2:0f:8b:c3:
 * 46:33:cf:e9:ff:82:bd:a1:e5:a0:60:ec:42:54:3b:07:ca:7f:
 * 80:96:b5:23:59:93:f6:b0:01:73:84:63:d8:56:2a:89:2b:b2:
 * 81:ba:b5:31:83:27:09:ee:ad:8a:80:b1:f9:98:58:28:f6:0b:
 * d5:77:95:39:16:b5:a3:d0:b2:df:dd:ea:4b:a2:57:02:d8:32:
 * e1:af:2a:e8:54:0f:02:5a:b8:5f:b2:5c:9c:e6:06:5c:23:18:
 * a1:cf:39:ce:11:1a:59:4c 
 * -----BEGIN CERTIFICATE-----
 * MIIGCTCCA/GgAwIBAgIJAIs3jiDietbxMA0GCSqGSIb3DQEBBQUAMIGaMQswCQYD
 * VQQGEwJDSDEPMA0GA1UECAwGQWFyZ2F1MREwDwYDVQQHDAhXaW5kaXNjaDENMAsG
 * A1UECgwERkhOVzELMAkGA1UECwwCTlMxGTAXBgNVBAMMEENocmlzIFllcmVhenRp
 * YW4xMDAuBgkqhkiG9w0BCQEWIWNocmlzLnllcmVhenRpYW5Ac3R1ZGVudHMuZmhu
 * dy5jaDAeFw0xMTEwMDExMzU5MDlaFw0yMTA5MjgxMzU5MDlaMIGaMQswCQYDVQQG
 * EwJDSDEPMA0GA1UECAwGQWFyZ2F1MREwDwYDVQQHDAhXaW5kaXNjaDENMAsGA1UE
 * CgwERkhOVzELMAkGA1UECwwCTlMxGTAXBgNVBAMMEENocmlzIFllcmVhenRpYW4x
 * MDAuBgkqhkiG9w0BCQEWIWNocmlzLnllcmVhenRpYW5Ac3R1ZGVudHMuZmhudy5j
 * aDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALuICjiQO6PPOuKB8TQy
 * 98YX2ugnTOXriXX/C/zTa1+wAVbHFrRUhZ/xnhqQkbqZvKoeeJtVfc5c3vlCNR29
 * Pa7CtPkyuvIUDm9PYDydUuoACXz33zfvu2SDM4CpfbdwvPsWTD1r3VpAOdHdAQaN
 * 1AkzU4AvOpuUpuqJRsR5Bm4qfIsfXEJZtQD2CG32zPqX2JgicTHMah5ASYEPMq17
 * m6f4C3gP7BPUuubi2SH5YTjwx+50b4AFQ4ot3iF2oinUh9FsiCu/2fvg6fqDTc9r
 * a6a47B1M25UmZNGoIgdomTxaf7do+W2XzkUFMfeOoxnFou7MCStgPBSROZkjXaEj
 * cQAgX/2Zi65pTdkFqIUw/Y1csx6TDCkHr4CBSzZreykcNTW/kymfg7QXPYbHodkP
 * 4jguLcWhLWh4NVI89n6XAXL8CkIZc/89nfonk/FEAjDgmJVQAf8LVMFwzIe7W8ff
 * VDX2J8SZFB03RMvky18o6GmrD+efJ9eWo0RmQwTCFBqTwcRiQ2vUjJS98RZKvNaN
 * jhKGM5a9B5DuVk2KGo+Y0sDTogVmgKg8cNC37TSRFV3YiIkP/Pv0Ay4Vu4HjGnQP
 * HyiKDYR7Dh/IyoerlKWq71vlFSQ+u1yL/AR7Eika1ODFdnTgGh/bcJ9WrXGqkQxM
 * WOBNJtxh8zb2yBMM9rFQSiIFAgMBAAGjUDBOMB0GA1UdDgQWBBTM50yGWteEpm6W
 * LoQaHPRqLoWnpzAfBgNVHSMEGDAWgBTM50yGWteEpm6WLoQaHPRqLoWnpzAMBgNV
 * HRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4ICAQAEZVcTMv8HCpvfcn2WdW5+0lsl
 * 0TB2+9ueDN5pS9JfEy4CaEZPrWv4IQFNkjTG2KtdLIkPnY/roVDvwuirpg36ZaQS
 * Mm7iffnyK7I4qJpisnonnekNqEuzjvNV5fpxxQpe36seUV0tr4ve3QUcFy0d4p1p
 * 0MY8haImmNjCedeyiNYjobjEVG1ZnH2d2/bzTJKcmjHkMr69F9WLmbrNZawaarLB
 * FRlFzWzh/I7q1U0zHNQEA0lLjWITyX4/g6L976HWppNABg31YniLWryNmtL7o1zZ
 * sPkxaSLI812Qw3N97J9ZEvv5TOF207rHk3vTHTw8+hxUG+e/D+BfywxaM141qgiC
 * eMHf/6TtUNr5UamhldWZrdziFC5+9kQwlsgL4LfDupMO0wXVPRepbPUSA5J6e9P2
 * YJ88177MrRUQqbhQIep/PEpMGc6fDqy3eHgw1rdikQbhwebLdhWB/NAdNrIPp4Ka
 * S7sekF5If4e9rN+bAIqHDPvq5HrVYG5q+Ov0mcChsNUvxofUMh7d6Th9vaaFzFqO
 * beqRtsM3lfIPi8NGM8/p/4K9oeWgYOxCVDsHyn+AlrUjWZP2sAFzhGPYViqJK7KB
 * urUxgycJ7q2KgLH5mFgo9gvVd5U5FrWj0LLf3epLolcC2DLhryroVA8CWrhfslyc
 * 5gZcIxihzznOERpZTA== 
 * -----END CERTIFICATE-----
 */

public class SimpleVerifier {
	
	public static final String FILEPATH = "res/chrisycert-sha1.cer";
	
	public static final Logger logger = Logger.getLogger("SimpleVerifier");	
	
	private FileInputStream fin;
	public X509Certificate certificate;
	
	//indicates if the certificate is valid
	private boolean valid;	
		
	/**
	 * Reads and attempts to parse given input file into a x509Certificate Object
	 * @param path, Path to certificate file
	 */
	public SimpleVerifier(String path){
			try {
				valid = true;
				this.fin = new FileInputStream(path);
				CertificateFactory x509CertFact = CertificateFactory.getInstance("X.509");
				certificate = (X509Certificate)x509CertFact.generateCertificate(this.fin);
			} catch (FileNotFoundException e) {
				logger.fatal("Could not open file: "+ path + "Reason: " + e.getMessage());
			} catch (CertificateException e) {
				logger.fatal("Error while parsing certificate from file: " + e.getMessage());
			}
	}
	
	/**
	 * This method automatically returns false if the certificate hasn't been
	 * checked yet.
	 * @return boolean if certificate is valid. In case of false the certificate
	 * has either expired or bogus. For expiration {@link #verifyValidity()}
	 */
	public boolean certificateIsValid(){
		return this.valid;
	}
	
	/**
	 * Marks the certificate as invalid
	 */
	private void invalidate(){
		this.valid = false;
	}
	
	/**
	 * Checks if Certificate is still valid for today
	 * @return
	 */
	public boolean checkValidity(){
		return this.checkValidity(new Date());
	}
	/**
	 * Checks if Certificate is still valid
	 * @param date, date to check against the certificate
	 * @return boolean, if the certificate has already expired or not
	 */
	private boolean checkValidity(Date date){
		Date validuntil = certificate.getNotAfter();
		Date validform = certificate.getNotBefore();
		return (date.after(validform) && date.before(validuntil));
	}
	/**
	 * Checks if the certificate Issuer and the Subject are the same entity.
	 * Self-signed certificates should only be trusted if the thumb-print to the certificate
	 * matches with the thumb-print the other parties has. Otherwise the certificated might
	 * have been modified.
	 * @return if the certificate is self-signed
	 */
	public boolean isSelfSignedCertificate(){
		/*
		 * expected principal and issuer name: CN=Chris Yereaztian,OU=NS,O=FHNW,L=Windisch,ST=Aargau,C=CH
		 */
		boolean result = false;
		X500Principal principal = certificate.getIssuerX500Principal();
		String principalname = principal.getName();
		X500Principal subject = certificate.getSubjectX500Principal();
		String subjectnameString = subject.getName();
		result = subjectnameString.equals(principalname);
		//check if the issuers name and the subjects name are the same
		logger.debug("Certificates Principal: " + principalname);
		logger.debug("Certificate issued to Subject: " + subjectnameString);
		return result;
	}
	
	/**
	 * Verifies that the Algorithm specified in the certificate
	 * @return 
	 */
	public boolean checkAlgorithm(){
		String algorithm = certificate.getSigAlgName();
		try {
			Signature signature = Signature.getInstance(algorithm);
			Provider provid = signature.getProvider();
			System.out.println(provid.getName());
			return algorithm.equalsIgnoreCase("SHA1WITHRSA");
		} catch (NoSuchAlgorithmException e) {
			logger.debug("Invalid algorithm found in signature" + e.getMessage());
			return false;
		}
	}
	
	/**
	 * Method that tries to retrieve a value from a certificate in DER-Format based on the
	 * Object Identifier
	 * The OID string is represented by a set of nonnegative whole numbers separated by periods. 
	 * For example:
	 * OID (Object Identifier) Extension Name 
	 * 2.5.29.14 SubjectKeyIdentifier 
	 * 2.5.29.15 KeyUsage  
	 * 2.5.29.16 PrivateKeyUsage 
	 * 2.5.29.17 SubjectAlternativeName 
	 * 2.5.29.18 IssuerAlternativeName 
	 * 2.5.29.19 BasicConstraints 
	 * 2.5.29.30 NameConstraints 
	 * 2.5.29.33 PolicyMappings 
	 * 2.5.29.35 AuthorityKeyIdentifier 
	 * 2.5.29.36 PolicyConstraints 
	 * @param X509Certificate
	 * @param oid  the Object Identifier value for the extension. 
	 * @return the DER-decoded string of the extension value or null if it is not present.
	 * @throws IOException
	 */
	private String getExtensionValue(X509Certificate X509Certificate, String oid) throws IOException
	{
	    String decoded = null;
	    byte[] extensionValue = X509Certificate.getExtensionValue(oid);

	    if (extensionValue != null)
	    {
	        DERObject derObject = toDERObject(extensionValue);
	        if (derObject instanceof DEROctetString)
	        {
	            DEROctetString derOctetString = (DEROctetString) derObject;

	            derObject = toDERObject(derOctetString.getOctets());
	            if (derObject instanceof DERUTF8String)
	            {
	                DERUTF8String s = DERUTF8String.getInstance(derObject);
	                decoded = s.getString();
	            }

	        }
	    }
	    return decoded;
	}
	
	/**
	 * Helper Method that takes a ByteInputStream and tries to parse the Data
	 * as a DER-Object specified via the ANS.1 standard
	 * @param data, raw ByteInputStream 
	 * @return DERObject - decoded object from the ByteInputStream 
	 * @throws IOException
	 */
	private DERObject toDERObject(byte[] data) throws IOException
	{
	    ByteArrayInputStream inStream = new ByteArrayInputStream(data);
	    ASN1InputStream asnInputStream = new ASN1InputStream(inStream);

	    return asnInputStream.readObject();
	}
	
	/**
	 * Checks if the thumb-print of the certificate matches with the calculated thumb-print
	 * @return true when thumb-print matches,
	 */
	public boolean checkThumbPrint(){
		String thumbprint = "964a9ce64af894dfafd4836b0c6351d7d30cc31d";
		try {
			return thumbprint.equals(getThumbPrint());
		} catch (CertificateEncodingException e) {
			logger.fatal("Could not calculate thumbprint from certificate." +
					"Certificate might be ");
			return false;
		} catch (NoSuchAlgorithmException e) {
			logger.fatal("Wrong algorithm specified: " + e.getMessage());
			this.invalidate();
			return false;
		}
	
	}
	
	/**
	 * Calculates thumb-print of the certificate
	 * @return Hex representation of the thumb print as a string
	 * @throws NoSuchAlgorithmException
	 * @throws CertificateEncodingException
	 */
	private String getThumbPrint() 
	    	throws NoSuchAlgorithmException, CertificateEncodingException {
	    	MessageDigest md = MessageDigest.getInstance("SHA-1");
	    	byte[] der = certificate.getEncoded();
	    	md.update(der);
	    	byte[] digest = md.digest();
	    	String thumbprint = hexify(digest);
	    	logger.debug("Calculated thumbprint: " + thumbprint);
	    	return thumbprint;
	    
	    }
	
	/**
	 * Helper Method that converts the byte representation provided by the
	 * Message Digest Object into a human readable hex-string
	 * @param bytes Array, typically from a Message Digest
	 * @return Hex representation of the byte array.
	 */
	private String hexify (byte bytes[]) {

    	char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', 
    			'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

    	StringBuffer buf = new StringBuffer(bytes.length * 2);

        for (int i = 0; i < bytes.length; ++i) {
        	buf.append(hexDigits[(bytes[i] & 0xf0) >> 4]);
            buf.append(hexDigits[bytes[i] & 0x0f]);
        }

        return buf.toString();
    }
	
	public Set<String> retrieveBasicExtensionsValue(){
		Set<String> result = new HashSet<String>();
		Set<String> nonCritSet = certificate.getNonCriticalExtensionOIDs();
	     if (nonCritSet != null)
	         for (Iterator<String> i = nonCritSet.iterator(); i.hasNext();) {
	             String oid = (String)i.next();
	             try{
	            	 result.add(this.getExtensionValue(certificate, oid));
	             }
	             catch(IOException io){}
	             System.out.println(oid);
	         }
	     return result;
	}
	public Set<String> retrieveCriticalExtensionsValue(){
		Set<String> result = new HashSet<String>();
		Set<String> critSet = certificate.getCriticalExtensionOIDs();
		 if (critSet != null && !critSet.isEmpty()) {
		     System.out.println("Set of critical extensions:");
		     for (Iterator<String> i = critSet.iterator(); i.hasNext();) {
		         String oid = (String)i.next();
		         try {
					result.add(this.getExtensionValue(certificate, oid));
				} catch (IOException e) {}
		     }
		 }
		 return result;
	
	}
	/**
	 * Checks the signature by verifying it with the public key
	 * Beware: This method does not work correctly !! Needs to be fixed
	 * but we don't know how!
	 * @return
	 */
	public boolean checkSignature(){
		boolean result = true;
		try {
			Signature sign = Signature.getInstance("SHA1withRSA");
			PublicKey pkey = certificate.getPublicKey();
			sign.initVerify(pkey);
			result = sign.verify(certificate.getSignature());
		} catch (NoSuchAlgorithmException e) {
			logger.fatal("Security Provider not found: " + e.getMessage());
		} catch (InvalidKeyException e) {
			logger.fatal("Public Key is invalid: " + e.getMessage());
			
		} catch (SignatureException e) {
			logger.fatal("Signature is invalid: " + e.getMessage());
			this.invalidate();
		}
		return result;
	}
	
	/**
	 * Convenience Method that tries to check all attributes
	 */
	public void checkAll(){
		if (!this.checkAlgorithm()){this.invalidate();}
		else if (!this.checkValidity()) {this.invalidate();}
		else if (!this.checkThumbPrint()){this.invalidate();}
		else if (!this.isSelfSignedCertificate()){this.invalidate();}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// Set up a simple logger configuration that logs on the console.
		BasicConfigurator.configure();
		//sets loglevel
		logger.setLevel(Level.ALL);
		SimpleVerifier sv = new SimpleVerifier(FILEPATH);
		sv.checkAll();
		System.out.println("Is Certificated Valid: " +sv.certificateIsValid());

	}
}
